package com.company.myfirstjmixproject.listener;

import com.company.myfirstjmixproject.entity.OnboardingStatus;
import com.company.myfirstjmixproject.entity.User;
import com.company.myfirstjmixproject.entity.UserStep;
import io.jmix.core.DataManager;
import io.jmix.core.Id;
import io.jmix.core.event.EntityChangedEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

/**
 * Copyright(C) 2023 Cardinal Operations. All rights reserved.
 *
 * @author ZhaoBo (zhaobo@shanshu.ai)
 * @date 2023/1/31 5:04 PM
 */
@Component
public class UserStepEventListener {

    @Autowired
    private DataManager dataManager;

    /**
     * <p>
     * 框架会在每次保存修改UserStep至数据库，但是还没有提交数据库事务的时候调用该方法，如果方法抛出异常，则回滚事务
     * 注意⚠️：是有当使用DataManager处理数据时，才能出发EntityChangeEvent监听器，如果通过EntityManager或JDBC语句保存修改，则不会出发监听器
     * </p>
     *
     * @param event 方法接收一个EntityChangeEvent对象作为参数，其中包含更改实体的id,更改类型（create/update/delete）以及更改的属性
     */
    @EventListener
    public void onUserStepChangedBeforeCommit(EntityChangedEvent<UserStep> event) {
        User user;
        if (event.getType() != EntityChangedEvent.Type.DELETED) {
            Id<UserStep> userStepId = event.getEntityId();
            UserStep userStep = dataManager.load(userStepId).one();
            user = userStep.getUser();
        } else {
            Id<User> userId = event.getChanges().getOldReferenceId("user");
            if (userId == null) {
                throw new IllegalStateException("Cannot get User form deleted UserStep");
            }
            user = dataManager.load(userId).one();
        }
        long completedCount = user.getSteps().stream().filter(us -> us.getCompletedDate() != null).count();
        if (completedCount == 0) {
            user.setOnboardingStatus(OnboardingStatus.NOT_STARTED);
        } else if (completedCount == user.getSteps().size()) {
            user.setOnboardingStatus(OnboardingStatus.COMPLETED);
        } else {
            user.setOnboardingStatus(OnboardingStatus.IN_PROGRESS);
        }

        dataManager.save(user);
    }
}